/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * JADominioGeometrico.java
 *
 * Created on 17/05/2010, 10:36:49 AM
 */

package ui;

import java.awt.Color;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import modelo.ValoresGlobales;
import modelo.dominiogeometrico.DominioGeometrico;
import modelo.grafico.PuntoGrafico;
import modelo.grafico.SegmentoLineaGrafico;
import modelo.primitivas.Punto;
import modelo.primitivas.SegmentoLinea;
import no.geosoft.cc.graphics.GInteraction;
import no.geosoft.cc.graphics.GObject;
import no.geosoft.cc.graphics.GScene;
import no.geosoft.cc.graphics.GSegment;
import no.geosoft.cc.graphics.GStyle;
import no.geosoft.cc.graphics.GWindow;
//import no.geosoft.cc.graphics.GWindow;

/**
 *
 * @author ALVARO
 */
public class JADominioGeometrico extends javax.swing.JApplet implements GInteraction {

    /** Initializes the applet JADominioGeometrico */
    @Override
    public void init() {
        try {
            java.awt.EventQueue.invokeAndWait(new Runnable() {
                public void run() {
                    initComponents();
                }
            });
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        
        try{
            numColumnas = Integer.valueOf(getParameter("columnas"));
            numFilas = Integer.valueOf(getParameter("filas"));
        } catch (NumberFormatException ex) {
            System.out.println("Error en los parametros de entrada (columna - fila).");
            ex.printStackTrace();
        }

        mostrarDominio();
    }

    /** This method is called from within the init() method to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        panelMalla = new javax.swing.JPanel();
        barraMenu = new javax.swing.JMenuBar();
        menuArchivo = new javax.swing.JMenu();
        menuDominioGeometrico = new javax.swing.JMenu();
        menuDefinirOrigen = new javax.swing.JCheckBoxMenuItem();
        menuSeleccionarPuntos = new javax.swing.JCheckBoxMenuItem();
        menuCrearSegmentos = new javax.swing.JCheckBoxMenuItem();
        menuSeleccionarSegmentos = new javax.swing.JCheckBoxMenuItem();
        menuLimpiar = new javax.swing.JCheckBoxMenuItem();

        panelMalla.setBackground(new java.awt.Color(255, 255, 255));
        panelMalla.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        panelMalla.setPreferredSize(new java.awt.Dimension(750, 550));
        panelMalla.setLayout(new java.awt.BorderLayout());

        barraMenu.setDoubleBuffered(true);

        menuArchivo.setText("Archivo");
        barraMenu.add(menuArchivo);

        menuDominioGeometrico.setText("Dominio Geométrico");

        menuDefinirOrigen.setText("Definir origen");
        menuDefinirOrigen.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuDefinirOrigenActionPerformed(evt);
            }
        });
        menuDominioGeometrico.add(menuDefinirOrigen);

        menuSeleccionarPuntos.setText("Seleccionar puntos");
        menuSeleccionarPuntos.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuSeleccionarPuntosActionPerformed(evt);
            }
        });
        menuDominioGeometrico.add(menuSeleccionarPuntos);

        menuCrearSegmentos.setText("Crear Segmentos");
        menuCrearSegmentos.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuCrearSegmentosActionPerformed(evt);
            }
        });
        menuDominioGeometrico.add(menuCrearSegmentos);

        menuSeleccionarSegmentos.setText("Seleccionar Segmentos");
        menuSeleccionarSegmentos.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuSeleccionarSegmentosActionPerformed(evt);
            }
        });
        menuDominioGeometrico.add(menuSeleccionarSegmentos);

        menuLimpiar.setText("Limpiar");
        menuLimpiar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuLimpiarActionPerformed(evt);
            }
        });
        menuDominioGeometrico.add(menuLimpiar);

        barraMenu.add(menuDominioGeometrico);

        setJMenuBar(barraMenu);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(panelMalla, javax.swing.GroupLayout.DEFAULT_SIZE, 502, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(panelMalla, javax.swing.GroupLayout.DEFAULT_SIZE, 326, Short.MAX_VALUE)
        );
    }// </editor-fold>//GEN-END:initComponents

    private void menuSeleccionarPuntosActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuSeleccionarPuntosActionPerformed
        // TODO add your handling code here:
        System.out.println("se selecciono SeleccionarPuntos. Estado =  " + menuSeleccionarPuntos.isSelected());
        menuDefinirOrigen.setSelected(false);
        menuLimpiar.setSelected(false);
        menuCrearSegmentos.setSelected(false);
        menuSeleccionarSegmentos.setSelected(false);

    }//GEN-LAST:event_menuSeleccionarPuntosActionPerformed

    private void menuDefinirOrigenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuDefinirOrigenActionPerformed
        // TODO add your handling code here:
        System.out.println("se selecciono Definir Origen. Estado =  " + menuDefinirOrigen.isSelected());
        menuSeleccionarPuntos.setSelected(false);
        menuLimpiar.setSelected(false);
        menuCrearSegmentos.setSelected(false);
        menuSeleccionarSegmentos.setSelected(false);
    }//GEN-LAST:event_menuDefinirOrigenActionPerformed

    private void menuLimpiarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuLimpiarActionPerformed
        // TODO add your handling code here:
        System.out.println("se selecciono Limpiar." + menuLimpiar.isSelected());
        menuSeleccionarPuntos.setSelected(false);
        menuDefinirOrigen.setSelected(false);
        menuCrearSegmentos.setSelected(false);
        menuSeleccionarSegmentos.setSelected(false);
    }//GEN-LAST:event_menuLimpiarActionPerformed

    private void menuCrearSegmentosActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuCrearSegmentosActionPerformed
        // TODO add your handling code here:
        System.out.println("se selecciono Segmentos." + menuCrearSegmentos.isSelected());
        menuSeleccionarPuntos.setSelected(false);
        menuDefinirOrigen.setSelected(false);
        menuLimpiar.setSelected(false);
        menuSeleccionarSegmentos.setSelected(false);
    }//GEN-LAST:event_menuCrearSegmentosActionPerformed

    private void menuSeleccionarSegmentosActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuSeleccionarSegmentosActionPerformed
        // TODO add your handling code here:
        System.out.println("Opción SELECCIONAR SEGMENTOS." + menuSeleccionarSegmentos.isSelected());
        menuSeleccionarPuntos.setSelected(false);
        menuDefinirOrigen.setSelected(false);
        menuLimpiar.setSelected(false);
        menuCrearSegmentos.setSelected(false);

    }//GEN-LAST:event_menuSeleccionarSegmentosActionPerformed


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuBar barraMenu;
    private javax.swing.JMenu menuArchivo;
    private javax.swing.JCheckBoxMenuItem menuCrearSegmentos;
    private javax.swing.JCheckBoxMenuItem menuDefinirOrigen;
    private javax.swing.JMenu menuDominioGeometrico;
    private javax.swing.JCheckBoxMenuItem menuLimpiar;
    private javax.swing.JCheckBoxMenuItem menuSeleccionarPuntos;
    private javax.swing.JCheckBoxMenuItem menuSeleccionarSegmentos;
    private javax.swing.JPanel panelMalla;
    // End of variables declaration//GEN-END:variables
    private DominioGeometrico miDominio;
    GWindow ventanaDibujo;
    GScene scene;
    private GStyle estiloPuntoNormal;
    private GStyle estiloPuntoOrigen;
    private GStyle estiloPuntoCandidato;
    private GStyle estiloPuntoSeleccionado;
    private GStyle estiloLineaSeleccionada;
    GSegment puntoInicialDeLinea = null;
    GSegment puntoFinalDeLinea = null;
    private GObject bandaDeSeleccion;
    private GSegment segmentoOrigen = null;
    private Collection puntosSeleccionados;
    private Collection grupoDeLineasSeleccionadas;
    private Integer numColumnas = null;
    private Integer numFilas    = null;
    private int mouseX0,  mouseY0;

/**
 * Grafica el dominio geometrico
 */
    public void mostrarDominio()
    {
        double extensionDelMundoEnX = 1000;
        double extensionDelMundoEnY = 1000;
        miDominio = new DominioGeometrico();
        miDominio.getGrillaDominio().setExtensionX(extensionDelMundoEnX);
        miDominio.getGrillaDominio().setExtensionY(extensionDelMundoEnY);
        
        if(numColumnas != null && numColumnas != null)
          {
            miDominio.getGrillaDominio().setColumnas(numColumnas.intValue());
            miDominio.getGrillaDominio().setFilas(numFilas.intValue());
          }
        else
          {
            miDominio.getGrillaDominio().setColumnas(ValoresGlobales.TOTAL_COLUMNAS);
            miDominio.getGrillaDominio().setFilas(ValoresGlobales.TOTAL_FILAS);
          }

        int puntosEnX = miDominio.getGrillaDominio().getColumnas();
        int puntosEnY = miDominio.getGrillaDominio().getFilas();
        double espacioEntrePuntosX = extensionDelMundoEnX / puntosEnX;
        double espacioEntrePuntosY = extensionDelMundoEnY / puntosEnY;

        int c = 0;
        int i = 0;
        double acumuladoX = 0;
        double acumuladoY = 0;

        panelMalla.removeAll();
        ventanaDibujo = new GWindow(new Color(255, 255, 255));
        panelMalla.add(ventanaDibujo.getCanvas());

        scene = new GScene(ventanaDibujo,"MiVentana");
        scene.setWorldExtent(0.0, 0.0, extensionDelMundoEnX, extensionDelMundoEnY);

        for (c = 0; c < puntosEnX + 1; c++)
          {
            GObject object = new PuntoGrafico(acumuladoX, acumuladoY);
            for (i = 0; i < puntosEnY + 1; i++)
              {
                object = new PuntoGrafico(acumuladoX, acumuladoY);
                //object.setStyle(estiloPuntoNormal);
                scene.add(object);
                acumuladoY += espacioEntrePuntosY;
              }
            scene.add(object);
            acumuladoX += espacioEntrePuntosX;
            acumuladoY = 0;
         }

        estiloPuntoSeleccionado = new GStyle();
        estiloPuntoSeleccionado.setForegroundColor(new Color(117, 146, 60));
        estiloPuntoSeleccionado.setBackgroundColor(new Color(117, 146, 60));
        estiloPuntoSeleccionado.setLineWidth(2);

        estiloPuntoOrigen = new GStyle();
        estiloPuntoOrigen.setForegroundColor(new Color(255, 102, 0));
        //estiloPuntoOrigen.setBackgroundColor(new Color(255, 102, 0));
        estiloPuntoOrigen.setBackgroundColor(Color.RED);
        estiloPuntoOrigen.setLineWidth(5);

        estiloPuntoNormal = new GStyle();
        estiloPuntoNormal.setForegroundColor(new Color(242, 221, 220));
        estiloPuntoNormal.setBackgroundColor(new Color(242, 221, 220));
        estiloPuntoNormal.setLineWidth(1);

        estiloPuntoCandidato = new GStyle();
        estiloPuntoCandidato.setForegroundColor(new Color(149, 179, 215));
        estiloPuntoCandidato.setBackgroundColor(new Color(149, 179, 215));
        estiloPuntoCandidato.setLineWidth(2);

        estiloLineaSeleccionada = new GStyle();
        estiloLineaSeleccionada.setForegroundColor(new Color(83, 142, 213));
        estiloLineaSeleccionada.setBackgroundColor(new Color(83, 142, 213));
        estiloLineaSeleccionada.setLineWidth(3);


        bandaDeSeleccion = new GObject("Interaction");
        GStyle rubberBandStyle = new GStyle();
        rubberBandStyle.setBackgroundColor(new Color(1.0f, 0.0f, 0.0f, 0.2f));
        bandaDeSeleccion.setStyle(rubberBandStyle);
        scene.add(bandaDeSeleccion);

        scene.draw();
        panelMalla.setVisible(rootPaneCheckingEnabled);
        setVisible(true);

        ventanaDibujo.startInteraction(this);
    }


    public void event(GScene gscene, int evento, int posX, int posY)
      {
        //throw new UnsupportedOperationException("Not supported yet.");
        //System.out.println("evento =" + evento + ",posX=" + posX + ", posY=" + posY);
        if(menuSeleccionarPuntos.isSelected())
          {
            seleccionarPuntos(gscene, evento, posX, posY);
          }
        else if(menuCrearSegmentos.isSelected())
          {
            crearSegmento(gscene, evento, posX, posY);
          }
        else if(menuDefinirOrigen.isSelected())
          {
            seleccionarOrigen(gscene, evento, posX, posY);
          }
        else if(menuLimpiar.isSelected())
          {
            limpiarDominio();
          }
        else if(menuSeleccionarSegmentos.isSelected())
          {
            seleccionarSegmentos(gscene, evento, posX, posY);
          }
    }


    public void seleccionarOrigen(GScene scene, int event, int x, int y)
      {

        if (event == GWindow.BUTTON1_UP /*|| event == GWindow.BUTTON2_UP*/)
          {
            /*boolean botonIzquierdoArriba = event == GWindow.BUTTON1_UP;
            if (botonIzquierdoArriba)
              {*/
                GSegment segmentoSeleccionado = scene.findSegment(x, y);
                if ((segmentoSeleccionado != null) && (segmentoSeleccionado.getOwner() instanceof PuntoGrafico))
                  {
                    System.out.println("se selecciono un punto");
                    if (segmentoOrigen != null)
                      {
                        if ((puntosSeleccionados != null) && (puntosSeleccionados.contains(segmentoOrigen)))
                          {
                            segmentoOrigen.setStyle(estiloPuntoSeleccionado);
                          }
                        else
                          {
                            segmentoOrigen.setStyle(estiloPuntoNormal);
                          }
                        PuntoGrafico puntoGraficoAnterior = (PuntoGrafico) segmentoOrigen.getOwner();
                        puntoGraficoAnterior.setEsOrigen(false);
                      }
                    segmentoOrigen = segmentoSeleccionado;
                    segmentoOrigen.setStyle(estiloPuntoOrigen);
                    PuntoGrafico puntoGraficoSeleccionado = (PuntoGrafico) segmentoOrigen.getOwner();
                    puntoGraficoSeleccionado.setEsOrigen(true);
                    miDominio.getGrillaDominio().setPuntoOrigen(puntoGraficoSeleccionado.getPuntoCoordenada());
                    menuDefinirOrigen.setSelected(false);
                  }
              //}
            scene.refresh();
        }
    }

    public void seleccionarPuntos(GScene scene, int event, int x, int y)
      {
        Set<Punto> setDePuntos = new HashSet<Punto>();
        Collection nuevosPuntosSeleccionados;
        if (puntosSeleccionados ==  null)
          {
            puntosSeleccionados  = new HashSet();
          }

        switch (event)
          {
            case GWindow.BUTTON1_DOWN:
                mouseX0 = x;
                mouseY0 = y;
                bandaDeSeleccion.addSegment(new GSegment());
                break;

            case GWindow.BUTTON1_UP:
                bandaDeSeleccion.removeSegments();
                scene.refresh();
                break;

            case GWindow.BUTTON1_DRAG:
                int[] xRubber = new int[]{mouseX0, x, x, mouseX0, mouseX0};
                int[] yRubber = new int[]{mouseY0, mouseY0, y, y, mouseY0};

                GSegment rubberBand = bandaDeSeleccion.getSegment();
                rubberBand.setGeometry(xRubber, yRubber);
                nuevosPuntosSeleccionados = scene.findSegmentsInside(Math.min(mouseX0, x),
                Math.min(mouseY0, y),
                Math.max(mouseX0, x),
                Math.max(mouseY0, y));

                // Remove rubber band from selection
                nuevosPuntosSeleccionados.remove(rubberBand);

                puntosSeleccionados.addAll(nuevosPuntosSeleccionados);

                // Set visual appaerance of new selection
                for (Iterator i = puntosSeleccionados.iterator(); i.hasNext();)
                  {
                    GSegment punto = (GSegment) i.next();
                    if (punto.getOwner() instanceof PuntoGrafico)
                      {
                        PuntoGrafico puntoGraficoSeleccionado = (PuntoGrafico) punto.getOwner();
                        if (!puntoGraficoSeleccionado.isOrigen())
                          {
                            punto.setStyle(estiloPuntoSeleccionado);
                          }
                        else
                          {
                            punto.setStyle(estiloPuntoOrigen);
                          }

                        setDePuntos.add(puntoGraficoSeleccionado.getPuntoCoordenada());
                      }
                  }

                miDominio.getConjuntoP().addAll(setDePuntos);
                //actualizarEtiquetas();

                scene.refresh();
                break;
        }

    }

    public void crearSegmento(GScene scene, int event, int x, int y) {

        if (event == GWindow.BUTTON1_UP ||
                event == GWindow.BUTTON2_UP) {

            boolean botonIzquierdoArriba = event == GWindow.BUTTON1_UP;
            if (botonIzquierdoArriba) {
                GSegment segmentoSeleccionado = scene.findSegment(x, y);
                //se valida que tanto el punto inicial como el final de cada segmento
                //de linea pertenezca al conjunto P -> (puntosSeleccionados.contains(segmentoSeleccionado))
                if ((segmentoSeleccionado != null) && (puntosSeleccionados.contains(segmentoSeleccionado)) && (segmentoSeleccionado.getOwner() instanceof PuntoGrafico)) {
                    if (puntoInicialDeLinea != null) {

                        PuntoGrafico puntoGraficoInicial = (PuntoGrafico) puntoInicialDeLinea.getOwner();
                        if ((puntosSeleccionados != null) && (puntosSeleccionados.contains(puntoInicialDeLinea))) {
                            if (puntoGraficoInicial.isOrigen()) {
                                puntoInicialDeLinea.setStyle(estiloPuntoOrigen);
                            } else {
                                puntoInicialDeLinea.setStyle(estiloPuntoSeleccionado);
                            }
                        } else {
                            if (puntoGraficoInicial.isOrigen()) {
                                puntoInicialDeLinea.setStyle(estiloPuntoOrigen);
                            } else {
                                puntoInicialDeLinea.setStyle(estiloPuntoNormal);
                            }
                        }

                        puntoFinalDeLinea = segmentoSeleccionado;
                        PuntoGrafico puntoGraficoFinal = (PuntoGrafico) segmentoSeleccionado.getOwner();

                        Punto puntoInicial = puntoGraficoInicial.getPuntoCoordenada();
                        Punto puntoFinal = puntoGraficoFinal.getPuntoCoordenada();

                        SegmentoLineaGrafico miSegmentoLineaGrafico = new SegmentoLineaGrafico(
                                puntoInicial, puntoFinal);

                        scene.add(miSegmentoLineaGrafico);
                        miSegmentoLineaGrafico.draw();

                        puntoInicialDeLinea = null;

                    } else {
                        puntoInicialDeLinea = segmentoSeleccionado;
                        puntoInicialDeLinea.setStyle(estiloPuntoCandidato);
                        PuntoGrafico puntoGraficoSeleccionado = (PuntoGrafico) puntoInicialDeLinea.getOwner();
                    }

                }
            }
            scene.refresh();

        }


    }

    public void seleccionarSegmentos(GScene scene, int event, int x, int y) {

        Set<SegmentoLinea> setDeLineas = new HashSet<SegmentoLinea>();


        switch (event) {
            case GWindow.BUTTON1_DOWN:
                mouseX0 = x;
                mouseY0 = y;
                bandaDeSeleccion.addSegment(new GSegment());
                break;

            case GWindow.BUTTON1_UP:
                bandaDeSeleccion.removeSegments();
                scene.refresh();
                break;

            case GWindow.BUTTON1_DRAG:
                int[] xRubber = new int[]{mouseX0, x, x, mouseX0, mouseX0};
                int[] yRubber = new int[]{mouseY0, mouseY0, y, y, mouseY0};

                GSegment rubberBand = bandaDeSeleccion.getSegment();
                rubberBand.setGeometry(xRubber, yRubber);



                // Undo visual selection of current selection
                if (grupoDeLineasSeleccionadas != null) {
                    for (Iterator i = grupoDeLineasSeleccionadas.iterator(); i.hasNext();) {
                        GSegment linea = (GSegment) i.next();
                        if (linea.getOwner() instanceof SegmentoLineaGrafico) {
                            SegmentoLineaGrafico segmentoLineaGraficoSeleccionado = (SegmentoLineaGrafico) linea.getOwner();
                            linea.setStyle(null);
                        }
                    }
                }


                //if (typeButton_.getText().equals("inside")) {
                grupoDeLineasSeleccionadas = scene.findSegmentsInside(Math.min(mouseX0, x),
                        Math.min(mouseY0, y),
                        Math.max(mouseX0, x),
                        Math.max(mouseY0, y));

                // Remove rubber band from selection
                grupoDeLineasSeleccionadas.remove(rubberBand);

                setDeLineas.clear();

                // Set visual appaerance of new selection
                for (Iterator i = grupoDeLineasSeleccionadas.iterator(); i.hasNext();) {
                    GSegment linea = (GSegment) i.next();
                    if (linea.getOwner() instanceof SegmentoLineaGrafico) {
                        SegmentoLineaGrafico segmentoLineaGraficoSeleccionado = (SegmentoLineaGrafico) linea.getOwner();
                        linea.setStyle(estiloLineaSeleccionada);

                        setDeLineas.add(segmentoLineaGraficoSeleccionado.getMiSegmentoLinea());
                    }


                }
                miDominio.getConjuntoS().addAll(setDeLineas);
                //ventanaPadre.getEvaluacionDominio().getDominioInicial().setConjuntoS(setDeLineas);
                //actualizarEtiquetas();
                scene.refresh();
                break;
        }
    }

    public void limpiarDominio()
    {
        scene.removeAll();
        miDominio.setConjuntoP(new HashSet());
        miDominio.setConjuntoS(new HashSet());
        miDominio.getGrillaDominio().setPuntoOrigen(new Punto(0, 0));
        miDominio.getConjuntoP().clear();
        miDominio.setConjuntoP(new HashSet());
        miDominio.setConjuntoS(new HashSet());
        miDominio.getGrillaDominio().setPuntoOrigen(new Punto(0, 0));

        puntosSeleccionados.clear();

        mostrarDominio();
        //actualizarEtiquetas();
        scene.refresh();
        menuLimpiar.setSelected(false);
    }

}
